package com.skp.shaphan.listeners;

import java.awt.Component;
import java.awt.Container;
import java.awt.Point;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.skp.shaphan.SQLEditorsPane;
import com.skp.shaphan.ShaphanApp;
import com.skp.shaphan.ui.SQLEditor;

public class MainMouseListener extends JPanel implements MouseListener, MouseMotionListener, HierarchyListener {

	private SQLEditor lastMousedEditor = null;
	
	public MainMouseListener() {
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addHierarchyListener(this);
		this.setVisible(true);
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		redispatchEvent(e);
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		redispatchEvent(e);
	}

	@Override
	public void mouseExited(MouseEvent e) {
		if(lastMousedEditor != null) {
			lastMousedEditor.setMousedOver(false);
			lastMousedEditor = null;
		}
		redispatchEvent(e);
	}

	@Override
	public void mousePressed(MouseEvent e) {
		redispatchEvent(e);
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		redispatchEvent(e);
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		redispatchEvent(e);
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		Point glassPanePoint = e.getPoint();
		SQLEditorsPane sqlEditors = ShaphanApp.getMainWindow().getSQLEditorsPane();
		Point sqlEditorsPoint = SwingUtilities.convertPoint(this, glassPanePoint, sqlEditors);
		
		boolean inTarget = true;
		if(sqlEditorsPoint.y < 0) {
			inTarget = false;
		}
		if(sqlEditorsPoint.y > sqlEditors.getHeight()) {
			inTarget = false;
		}
		if(sqlEditorsPoint.x < 0) {
			inTarget = false;
		}
		if(sqlEditorsPoint.x > sqlEditors.getWidth()) {
			inTarget = false;
		}
		if(inTarget) {
			Component c = SwingUtilities.getDeepestComponentAt(sqlEditors, sqlEditorsPoint.x, sqlEditorsPoint.y);
			SQLEditor editor = findEditor(c);
			if(editor == null) {
				// I think it might work better to leave the last editor moused over
				/*
				if(lastMousedEditor != null) {
					lastMousedEditor.setMousedOver(false);
					lastMousedEditor = null;
				}
				*/
			} else {
				editor.setMousedOver(true);
				if(lastMousedEditor != null) {
					// I gave each editor a unique name, so now I can compare the names intead of the object as a whole
					if(!lastMousedEditor.getName().equals(editor.getName())) {
						lastMousedEditor.setMousedOver(false);
					}
				}
				lastMousedEditor = editor;
			}
		}
		
		redispatchEvent(e);
	}
	
	private SQLEditor findEditor(Component c) {
		Component parent = c;
		while(parent != null) {
			if(parent instanceof SQLEditor) {
				return (SQLEditor)parent;
			}
			if(parent instanceof SQLEditorsPane) {
				return null;
			}
			parent = parent.getParent();
		}
		return null;
	}
	
	private void redispatchEvent(MouseEvent e) {
		ShaphanApp app = ShaphanApp.getMainWindow();
		Container contentPane = app.getContentPane();
		Component glassPane = this;
		Point contentPoint = SwingUtilities.convertPoint(glassPane, e.getPoint(), contentPane);
		if(contentPoint.y < 0) {
			contentPane = app.getJMenuBar();
			contentPoint = SwingUtilities.convertPoint(glassPane, e.getPoint(), contentPane);
		}

		Component targetComponent = SwingUtilities.getDeepestComponentAt(contentPane, contentPoint.x, contentPoint.y);
		if(targetComponent != null) {
			Point targetPoint = SwingUtilities.convertPoint(contentPane, contentPoint, targetComponent);

			targetComponent.dispatchEvent(new MouseEvent(targetComponent, e.getID(), e.getWhen(), e.getModifiers(), targetPoint.x, targetPoint.y, e.getClickCount(), e.isPopupTrigger()));
		}
	}

	@Override
	public void hierarchyChanged(HierarchyEvent arg0) {
		JLayeredPane l = (JLayeredPane)getParent();
		JFrame f = (JFrame)JOptionPane.getFrameForComponent(l);
		l.moveToBack(f.getContentPane());
		System.out.println("---");
		for(Component c : l.getComponents()) {
			System.out.println("-" + c.getClass().getName() + "-" + l.getLayer(c));
		}
	}

}
